"""
Case Type   : 故障&可靠性测试
Case Name   : 夏令时频繁创建修改删除schema
Create At   : 2021/01/27
Owner       : opengauss
Description :
    1、设置操作系统时区为new_york
    2、设置操作系统时间为2020-03-08凌晨01:58
    3、创建修改删除shcema1
    4、执行3的同时创建修改删除shcema2
    5、执行3的同时创建修改删除shcema3
    6、执行3的同时创建修改删除shcema4
    7.重复执行3-6 100次
Expect      :
    1.设置成功
    2.设置成功
    3.执行成功
    4.执行成功
    5.执行成功
    6.执行成功
    7.成功率100%
History     :
    Modified by @wan005 2021/3/23: 增加环境时区修复步骤
    Modified by ningyali 2024/7/9 优化用例解决一致性问题
"""
import datetime
import os
import unittest

from yat.test import Node
from yat.test import macro

from testcase.utils.ComThread import ComThread
from testcase.utils.Common import Common
from testcase.utils.CommonSH import CommonSH
from testcase.utils.CommonSH import RestartDbCluster
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger


class Ddldatabase(unittest.TestCase):
    nodes_tuple = ('PrimaryDbUser', 'Standby1DbUser', 'Standby2DbUser')

    @RestartDbCluster(*nodes_tuple)
    def setUp(self):
        self.log = Logger()
        self.log.info(f'----{os.path.basename(__file__)} 开始执行-----')
        self.root_nodes_tuple = ('PrimaryRoot', 'Standby1Root', 'Standby2Root')
        self.pri_sh = CommonSH('PrimaryDbUser')
        self.pri_user = self.pri_sh.node
        self.pri_root = Node(node='PrimaryRoot')
        self.sta1_root = Node(node='Standby1Root')
        self.constant = Constant()
        self.common = Common('PrimaryRoot')
        self.schema_name = [f'schema_dbsystem240_{i}' for i in range(1, 5)]
        self.new_york_local = '/usr/share/zoneinfo/America/New_York'
        self.ln_sf_cmd = 'ln -sf {zone} /etc/localtime'

        result = self.common.check_system_timezone(*self.root_nodes_tuple)
        self.log.info(result)
        self.assertTrue(result)

        self.current_time = self.pri_root.sh(
            "date '+%Y-%m-%d %H:%M:%S'").result()
        self.current_local_zone_str = self.pri_root.sh(
            "ls -l /etc/localtime").result()
        self.log.info(f"before dst. cache time is "
                      f"{self.current_time}, {self.current_local_zone_str}.")

        self.log.info('-----安装ntp服务-----')
        result = self.pri_root.sh('yum install -y ntp').result()
        self.log.info(result)
        result = self.pri_root.sh(
            'systemctl enable ntpd').result()
        self.log.info(result)
        result = self.pri_root.sh('systemctl start ntpd').result()
        self.log.info(result)

    def test_basebackup(self):
        self.log.info('-----1、设置操作系统时区为new_york-----')
        cmd = f'cp {macro.DB_INSTANCE_PATH}/postgresql.conf ' \
            f'{macro.DB_INSTANCE_PATH}/postgresql.conf.timezone;' \
            f'echo "timezone=America/New_York" >> ' \
            f'{macro.DB_INSTANCE_PATH}/postgresql.conf'
        self.log.info(cmd)
        result = self.pri_user.sh(cmd).result()
        self.log.info(result)
        result = self.pri_sh.reloadDbConfig()
        self.log.info(result)
        self.assertIn(self.constant.RELOAD_SUCCESS_MSG, result)

        self.log.info('-----2、设置操作系统时间为2020-03-08凌晨01:58-----')
        zonecmd = self.ln_sf_cmd.format(zone=self.new_york_local)
        self.log.info(zonecmd)
        result = self.pri_root.sh(zonecmd).result()
        self.log.info(result)
        self.log.info("设置操作系统时间为 03/08/2020 01:59:55(3月份第二个周日，即将开始夏令时)")
        datecmd = "date -s '03/08/2020 01:59:55';hwclock --systohc;" \
                  "service ntpd stop;ntpdate ntp.api.bz;service ntpd start"
        self.log.info(datecmd)
        result = self.pri_root.sh(datecmd).result()
        self.log.info(result)

        self.log.info('-----7.重复执行3-6 100次-----')
        for i in range(100):
            connect_thread = []
            self.log.info(f'-----round {i}-----')
            for thread_num in range(4):
                self.log.info(f'---create/alter/drop schema{thread_num}--')
                sql = f"create schema {self.schema_name[thread_num]};" \
                    f"alter schema {self.schema_name[thread_num]} " \
                    f"rename to {self.schema_name[thread_num]}_new;" \
                    f"drop schema if exists " \
                    f"{self.schema_name[thread_num]}_new;"
                connect_thread.append(ComThread(
                    self.pri_sh.executDbSql, args=(sql,)))
                connect_thread[thread_num].setDaemon(True)
                connect_thread[thread_num].start()

            for thread_num in range(4):
                self.log.info(f'-----检查线程结果{thread_num}-----')
                connect_thread[thread_num].join(60)
                result = connect_thread[thread_num].get_result()
                self.log.info(result)
                self.assertIn(self.constant.create_schema_success_msg, result)
                self.assertIn(self.constant.alter_schema_success_msg, result)
                self.assertIn(self.constant.drop_schema_success_msg, result)

    def tearDown(self):
        self.log.info('-----环境清理-----')
        self.log.info("-----恢复时间-----")
        cmd = f'cp {macro.DB_INSTANCE_PATH}/postgresql.conf.timezone' \
            f' {macro.DB_INSTANCE_PATH}/postgresql.conf; '
        self.pri_user.sh(cmd)
        result = self.pri_sh.reloadDbConfig()
        self.log.info(result)

        recover_timezone = self.current_local_zone_str.split('->')[1]
        zonecmd = self.ln_sf_cmd.format(zone=recover_timezone)
        self.log.info('recover: ' + zonecmd)
        self.pri_root.sh(zonecmd)

        current_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        datecmd = 'date -s \'{}\''.format(current_time)
        self.log.info('recover: ' + datecmd)
        self.pri_root.sh(datecmd)

        self.log.info('-----删除schema-----')
        for schname in self.schema_name:
            sql = f"drop schema if exists {schname} cascade;"
            result = self.pri_sh.executDbSql(sql)
            self.log.info(result)
        self.log.info(f'-----{os.path.basename(__file__)} 执行结束-----')